﻿using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Ioc.MvcApplication.Controllers;

namespace Ioc.MvcApplication
{
    public class MvcApplication : HttpApplication
    {
        private static IWindsorContainer _container;

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute("Default", "{controller}/{action}/{id}", new {controller = "Home", action = "Index", id = UrlParameter.Optional});
        }

        protected void Application_Start()
        {
            InitializeIoc();

            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

        protected void Application_End()
        {
            _container.Dispose();
        }

        private void InitializeIoc()
        {
            _container = new WindsorContainer().Register(
                Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient(),
                //Component.For<IRepository>().ImplementedBy<Repository>(),
                //Component.For<IRepository>().ImplementedBy<Repository>().LifestylePerWebRequest(),
                Classes.FromThisAssembly().Pick().WithServiceDefaultInterfaces().LifestyleTransient());

            ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container.Kernel));
        }

        private class WindsorControllerFactory : DefaultControllerFactory
        {
            public WindsorControllerFactory(IKernel kernel)
            {
                _kernel = kernel;
            }

            private readonly IKernel _kernel;

            public override void ReleaseController(IController controller)
            {
                _kernel.ReleaseComponent(controller);
            }

            protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
            {
                if (controllerType == null)
                {
                    throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
                }
                return (IController)_kernel.Resolve(controllerType);
            }
        }
    }
}